/****************************************************************
 * Fulguro
 * Copyright (C) 2004 Christophe Clienti
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 ***************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <flgrCoreDataIO.h>
#include <flgrCoreDispatch.h>
#include <flgrCoreVector.h>
#include <flgrCoreArithVector.h>
#include "flgrMeasureBase.h"
#include "flgrMeasureBaseSSE.h"
#include "flgrMeasureBaseSSE2.h"



/*!
 * \defgroup group_fulguro_measure Measurements
 * \brief Basic measurement operations
 * \defgroup group_fulguro_measure_basics Basics
 * \ingroup group_fulguro_measure
 * @{
 */





/******************************************************** 1D *********************************************************/



#define FLGR_MACRO_MEASURE1D_MIN_MAX(dtype)			\
  int i,k;							\
  int spp=dat->spp;						\
  int length=dat->length*spp;					\
  dtype *pdat = (dtype*) dat->array;				\
  dtype *pmini = (dtype*) mini->array;				\
  dtype *pmaxi = (dtype*) maxi->array;				\
  dtype val;							\
								\
  FLGR_DECLARE_FUNCTION;					\
								\
  for(k=0 ; k<spp ; k++) {					\
    pmini[k] = flgr_get_array_##dtype(pdat,k);			\
    pmaxi[k] = pmini[k];					\
								\
    for(i=spp+k ; i<length ; i+=spp) {				\
      val = flgr_get_array_##dtype(pdat,i);			\
      pmini[k] = FLGR_MIN(pmini[k],val);			\
      pmaxi[k] = FLGR_MAX(pmaxi[k],val);			\
    }								\
  }								\
  return


void flgr1d_measure_min_max_fgBIT(FLGR_Data1D *dat, FLGR_Vector *mini, FLGR_Vector *maxi) {
  FLGR_MACRO_MEASURE1D_MIN_MAX(fgBIT);
}

void flgr1d_measure_min_max_fgUINT8(FLGR_Data1D *dat, FLGR_Vector *mini, FLGR_Vector *maxi) {
#ifdef __SSE2__
    if(dat->spp==1) {
      flgr1d_measure_min_max_spp1_SSE2_fgUINT8(dat, mini, maxi);
    }else {
      FLGR_MACRO_MEASURE1D_MIN_MAX(fgUINT8);
    }
#else
  #ifdef __SSE__
    if(dat->spp==1) {
      flgr1d_measure_min_max_spp1_SSE_fgUINT8(dat, mini, maxi);
    }else {
      FLGR_MACRO_MEASURE1D_MIN_MAX(fgUINT8);
    }
  #else
    FLGR_MACRO_MEASURE1D_MIN_MAX(fgUINT8);
  #endif
#endif
}

void flgr1d_measure_min_max_fgUINT16(FLGR_Data1D *dat, FLGR_Vector *mini, FLGR_Vector *maxi) {
  FLGR_MACRO_MEASURE1D_MIN_MAX(fgUINT16);
}

void flgr1d_measure_min_max_fgUINT32(FLGR_Data1D *dat, FLGR_Vector *mini, FLGR_Vector *maxi) {
  FLGR_MACRO_MEASURE1D_MIN_MAX(fgUINT32);
}

void flgr1d_measure_min_max_fgINT8(FLGR_Data1D *dat, FLGR_Vector *mini, FLGR_Vector *maxi) {
  FLGR_MACRO_MEASURE1D_MIN_MAX(fgINT8);
}

void flgr1d_measure_min_max_fgINT16(FLGR_Data1D *dat, FLGR_Vector *mini, FLGR_Vector *maxi) {
#ifdef __SSE2__
    if(dat->spp==1) {
      flgr1d_measure_min_max_spp1_SSE2_fgINT16(dat, mini, maxi);
    }else {
      FLGR_MACRO_MEASURE1D_MIN_MAX(fgINT16);
    }
#else
  #ifdef __SSE__
    if(dat->spp==1) {
      flgr1d_measure_min_max_spp1_SSE_fgINT16(dat, mini, maxi);
    }else {
      FLGR_MACRO_MEASURE1D_MIN_MAX(fgINT16);
    }
  #else
    FLGR_MACRO_MEASURE1D_MIN_MAX(fgINT16);
  #endif
#endif
}

void flgr1d_measure_min_max_fgINT32(FLGR_Data1D *dat, FLGR_Vector *mini, FLGR_Vector *maxi) {
  FLGR_MACRO_MEASURE1D_MIN_MAX(fgINT32);
}

void flgr1d_measure_min_max_fgFLOAT32(FLGR_Data1D *dat, FLGR_Vector *mini, FLGR_Vector *maxi) {
  FLGR_MACRO_MEASURE1D_MIN_MAX(fgFLOAT32);
}

void flgr1d_measure_min_max_fgFLOAT64(FLGR_Data1D *dat, FLGR_Vector *mini, FLGR_Vector *maxi) {
  FLGR_MACRO_MEASURE1D_MIN_MAX(fgFLOAT64);
}

////////////////////////////////////////////////////////////////////////////
/*! Measure1d minimum and maximum
 *  @param dat : pointer to the FLGR_Data1D
 *  @param minimum : pointer a variable. Variable type must correspond with to dat->type
 *  @param maximum : pointer a variable. Variable type must correspond with to dat->type
 *  @returns FLGR_RET_OK, ...
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr1d_measure_min_max(FLGR_Data1D *dat, FLGR_Vector *minimum, FLGR_Vector *maximum) {
  FLGR_DECLARE_FUNCTION;

  if((dat==NULL) || (minimum==NULL) || (maximum==NULL)){
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  if(dat->spp != minimum->spp) {
    POST_ERROR("Sample per pixel are different\n");
    return FLGR_RET_UNDEFINED_ERROR;
  }

  if(dat->spp != maximum->spp) {
    POST_ERROR("Sample per pixel are different\n");
    return FLGR_RET_UNDEFINED_ERROR;
  }

  FLGR_DISPATCH_PROCEDURE(dat->type,flgr1d_measure_min_max,dat,minimum,maximum);

}



#define FLGR_MACRO_MEASURE1D_VOLUME_OLD(dtype,dtype_volume)		\
  FLGR_Vector *tmp = flgr_vector_create(dat->spp, dat->type);		\
  FLGR_Vector *tmp2 = flgr_vector_create(volume->spp, volume->type);	\
  int j;								\
									\
  FLGR_DECLARE_FUNCTION;						\
									\
  flgr_vector_clear(tmp);						\
  flgr_vector_clear(tmp2);						\
  flgr_vector_clear(volume);						\
  									\
  for(j=0 ; j<dat->length ; j++) {					\
    flgr1d_get_data_vector_##dtype(dat,j,tmp);				\
    flgr_vector_copy_##dtype_volume##_##dtype(tmp2,tmp);		\
    flgr_vector_add(volume,tmp2,volume);				\
  }									\
									\
  flgr_vector_destroy(tmp);						\
  flgr_vector_destroy(tmp2);						\
									\
  return


#define FLGR_MACRO_MEASURE1D_VOLUME(dtype,dtype_volume)	\
  int i,k;							\
  int spp=dat->spp;						\
  int length=dat->length*spp;					\
  dtype *pdat = (dtype*) dat->array;				\
  dtype_volume *pvol = (dtype_volume*) volume->array;		\
  dtype val;							\
								\
  FLGR_DECLARE_FUNCTION;					\
								\
  for(k=0 ; k<spp ; k++) {					\
    pvol[k] = flgr_get_array_##dtype(pdat,k);			\
 								\
    for(i=spp+k ; i<length ; i+=spp) {				\
      val = flgr_get_array_##dtype(pdat,i);			\
      pvol[k] += (dtype_volume)(val);				\
    }								\
  }								\
  return


void flgr1d_measure_volume_u32_fgBIT(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgBIT,fgUINT32);
}
void flgr1d_measure_volume_u32_fgUINT8(FLGR_Data1D *dat, FLGR_Vector *volume) {
#ifdef __SSE2__
    if(dat->spp==1) {
      flgr1d_measure_volume_u32_spp1_SSE2_fgUINT8(dat, volume);
    }else {
      FLGR_MACRO_MEASURE1D_VOLUME(fgUINT8,fgUINT32);
    }
#else
  #ifdef __SSE__
      if(dat->spp==1) {
        flgr1d_measure_volume_u32_spp1_SSE_fgUINT8(dat, volume);
      }else {
        FLGR_MACRO_MEASURE1D_VOLUME(fgUINT8,fgUINT32);
      }
  #else
    FLGR_MACRO_MEASURE1D_VOLUME(fgUINT8,fgUINT32);
  #endif
#endif
}
void flgr1d_measure_volume_u32_fgUINT16(FLGR_Data1D *dat, FLGR_Vector *volume) {
#ifdef __SSE2__
    if(dat->spp==1) {
      flgr1d_measure_volume_u32_spp1_SSE2_fgUINT16(dat, volume);
    }else {
      FLGR_MACRO_MEASURE1D_VOLUME(fgUINT16,fgUINT32);
    }
#else
  #ifdef __SSE__
      if(dat->spp==1) {
        flgr1d_measure_volume_u32_spp1_SSE_fgUINT16(dat, volume);
      }else {
        FLGR_MACRO_MEASURE1D_VOLUME(fgUINT16,fgUINT32);
      }
  #else
    FLGR_MACRO_MEASURE1D_VOLUME(fgUINT16,fgUINT32);
  #endif
#endif
}
void flgr1d_measure_volume_u32_fgUINT32(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgUINT32,fgUINT32);
}
void flgr1d_measure_volume_u32_fgINT8(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgINT8,fgUINT32);
}
void flgr1d_measure_volume_u32_fgINT16(FLGR_Data1D *dat, FLGR_Vector *volume) {
#ifdef __SSE2__
    if(dat->spp==1) {
      flgr1d_measure_volume_u32_spp1_SSE2_fgINT16(dat, volume);
    }else {
      FLGR_MACRO_MEASURE1D_VOLUME(fgINT16,fgUINT32);
    }
#else
  #ifdef __SSE__
      if(dat->spp==1) {
        flgr1d_measure_volume_u32_spp1_SSE_fgINT16(dat, volume);
      }else {
        FLGR_MACRO_MEASURE1D_VOLUME(fgINT16,fgUINT32);
      }
  #else
    FLGR_MACRO_MEASURE1D_VOLUME(fgINT16,fgUINT32);
  #endif
#endif
}
void flgr1d_measure_volume_u32_fgINT32(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgINT32,fgUINT32);
}
void flgr1d_measure_volume_u32_fgFLOAT32(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgFLOAT32,fgUINT32);
}
void flgr1d_measure_volume_u32_fgFLOAT64(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgFLOAT64,fgUINT32);
}




void flgr1d_measure_volume_s32_fgBIT(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgBIT,fgINT32);
}
void flgr1d_measure_volume_s32_fgUINT8(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgUINT8,fgINT32);
}
void flgr1d_measure_volume_s32_fgUINT16(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgUINT16,fgINT32);
}
void flgr1d_measure_volume_s32_fgUINT32(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgUINT32,fgINT32);
}
void flgr1d_measure_volume_s32_fgINT8(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgINT8,fgINT32);
}
void flgr1d_measure_volume_s32_fgINT16(FLGR_Data1D *dat, FLGR_Vector *volume) {
#ifdef __SSE2__
    if(dat->spp==1) {
      flgr1d_measure_volume_s32_spp1_SSE2_fgINT16(dat, volume);
    }else {
      FLGR_MACRO_MEASURE1D_VOLUME(fgINT16,fgINT32);
    }
#else
  #ifdef __SSE__
      if(dat->spp==1) {
         flgr1d_measure_volume_s32_spp1_SSE_fgINT16(dat, volume);
      }else {
        FLGR_MACRO_MEASURE1D_VOLUME(fgINT16,fgINT32);
      }
  #else
    FLGR_MACRO_MEASURE1D_VOLUME(fgINT16,fgINT32);
  #endif
#endif
}
void flgr1d_measure_volume_s32_fgINT32(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgINT32,fgINT32);
}
void flgr1d_measure_volume_s32_fgFLOAT32(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgFLOAT32,fgINT32);
}
void flgr1d_measure_volume_s32_fgFLOAT64(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgFLOAT64,fgINT32);
}





void flgr1d_measure_volume_u64_fgBIT(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgBIT,fgUINT64);
}
void flgr1d_measure_volume_u64_fgUINT8(FLGR_Data1D *dat, FLGR_Vector *volume) {
#ifdef __SSE2__
    if(dat->spp==1) {
      flgr1d_measure_volume_u64_spp1_SSE2_fgUINT8(dat, volume);
    }else {
      FLGR_MACRO_MEASURE1D_VOLUME(fgUINT8,fgUINT64);
    }
#else
  FLGR_MACRO_MEASURE1D_VOLUME(fgUINT8,fgUINT64);
#endif
}
void flgr1d_measure_volume_u64_fgUINT16(FLGR_Data1D *dat, FLGR_Vector *volume) {
#ifdef __SSE2__
    if(dat->spp==1) {
      flgr1d_measure_volume_u64_spp1_SSE2_fgUINT16(dat, volume);
    }else {
      FLGR_MACRO_MEASURE1D_VOLUME(fgUINT16,fgUINT64);
    }
#else
    FLGR_MACRO_MEASURE1D_VOLUME(fgUINT16,fgUINT64);
#endif
}
void flgr1d_measure_volume_u64_fgUINT32(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgUINT32,fgUINT64);
}
void flgr1d_measure_volume_u64_fgINT8(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgINT8,fgUINT64);
}
void flgr1d_measure_volume_u64_fgINT16(FLGR_Data1D *dat, FLGR_Vector *volume) {
#ifdef __SSE2__
    if(dat->spp==1) {
      flgr1d_measure_volume_u64_spp1_SSE2_fgINT16(dat, volume);
    }else {
      FLGR_MACRO_MEASURE1D_VOLUME(fgINT16,fgUINT64);
    }
#else
    FLGR_MACRO_MEASURE1D_VOLUME(fgINT16,fgUINT64);
#endif
}
void flgr1d_measure_volume_u64_fgINT32(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgINT32,fgUINT64);
}
void flgr1d_measure_volume_u64_fgFLOAT32(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgFLOAT32,fgUINT64);
}
void flgr1d_measure_volume_u64_fgFLOAT64(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgFLOAT64,fgUINT64);
}




void flgr1d_measure_volume_s64_fgBIT(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgBIT,fgINT64);
}
void flgr1d_measure_volume_s64_fgUINT8(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgUINT8,fgINT64);
}
void flgr1d_measure_volume_s64_fgUINT16(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgUINT16,fgINT64);
}
void flgr1d_measure_volume_s64_fgUINT32(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgUINT32,fgINT64);
}
void flgr1d_measure_volume_s64_fgINT8(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgINT8,fgINT64);
}
void flgr1d_measure_volume_s64_fgINT16(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgINT16,fgINT64);
}
void flgr1d_measure_volume_s64_fgINT32(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgINT32,fgINT64);
}
void flgr1d_measure_volume_s64_fgFLOAT32(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgFLOAT32,fgINT64);
}
void flgr1d_measure_volume_s64_fgFLOAT64(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgFLOAT64,fgINT64);
}








void flgr1d_measure_volume_f32_fgBIT(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgBIT,fgFLOAT32);
}
void flgr1d_measure_volume_f32_fgUINT8(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgUINT8,fgFLOAT32);
}
void flgr1d_measure_volume_f32_fgUINT16(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgUINT16,fgFLOAT32);
}
void flgr1d_measure_volume_f32_fgUINT32(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgUINT32,fgFLOAT32);
}
void flgr1d_measure_volume_f32_fgINT8(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgINT8,fgFLOAT32);
}
void flgr1d_measure_volume_f32_fgINT16(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgINT16,fgFLOAT32);
}
void flgr1d_measure_volume_f32_fgINT32(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgINT32,fgFLOAT32);
}
void flgr1d_measure_volume_f32_fgFLOAT32(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgFLOAT32,fgFLOAT32);
}
void flgr1d_measure_volume_f32_fgFLOAT64(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgFLOAT64,fgFLOAT32);
}




void flgr1d_measure_volume_f64_fgBIT(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgBIT,fgFLOAT64);
}
void flgr1d_measure_volume_f64_fgUINT8(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgUINT8,fgFLOAT64);
}
void flgr1d_measure_volume_f64_fgUINT16(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgUINT16,fgFLOAT64);
}
void flgr1d_measure_volume_f64_fgUINT32(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgUINT32,fgFLOAT64);
}
void flgr1d_measure_volume_f64_fgINT8(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgINT8,fgFLOAT64);
}
void flgr1d_measure_volume_f64_fgINT16(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgINT16,fgFLOAT64);
}
void flgr1d_measure_volume_f64_fgINT32(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgINT32,fgFLOAT64);
}
void flgr1d_measure_volume_f64_fgFLOAT32(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgFLOAT32,fgFLOAT64);
}
void flgr1d_measure_volume_f64_fgFLOAT64(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE1D_VOLUME(fgFLOAT64,fgFLOAT64);
}



#define FLGR_MEASURE_VOLUME1D_PREDISPATCH(dtype,vector_type,...)	\
  switch(vector_type) {							\
  case FLGR_UINT32:							\
    flgr1d_measure_volume_u32_##dtype(__VA_ARGS__);break;		\
  case FLGR_UINT64:							\
    flgr1d_measure_volume_u64_##dtype(__VA_ARGS__);break;		\
  case FLGR_INT32:							\
    flgr1d_measure_volume_s32_##dtype(__VA_ARGS__);break;		\
  case FLGR_INT64:							\
    flgr1d_measure_volume_s64_##dtype(__VA_ARGS__);break;		\
  case FLGR_FLOAT32:							\
    flgr1d_measure_volume_f32_##dtype(__VA_ARGS__);break;		\
  case FLGR_FLOAT64:							\
    flgr1d_measure_volume_f64_##dtype(__VA_ARGS__);break;		\
  default:								\
    POST_ERROR("Unsupported volume vector type : %s\n",			\
	       flgr_get_type_string(vector_type));			\
  }									\
  return



void flgr1d_measure_volume_fgBIT(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MEASURE_VOLUME1D_PREDISPATCH(fgBIT,volume->type,dat,volume);
}
void flgr1d_measure_volume_fgUINT8(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MEASURE_VOLUME1D_PREDISPATCH(fgUINT8,volume->type,dat,volume);
}
void flgr1d_measure_volume_fgUINT16(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MEASURE_VOLUME1D_PREDISPATCH(fgUINT16,volume->type,dat,volume);
}
void flgr1d_measure_volume_fgUINT32(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MEASURE_VOLUME1D_PREDISPATCH(fgUINT32,volume->type,dat,volume);
}
void flgr1d_measure_volume_fgINT8(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MEASURE_VOLUME1D_PREDISPATCH(fgINT8,volume->type,dat,volume);
}
void flgr1d_measure_volume_fgINT16(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MEASURE_VOLUME1D_PREDISPATCH(fgINT16,volume->type,dat,volume);
}
void flgr1d_measure_volume_fgINT32(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MEASURE_VOLUME1D_PREDISPATCH(fgINT32,volume->type,dat,volume);
}
void flgr1d_measure_volume_fgFLOAT32(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MEASURE_VOLUME1D_PREDISPATCH(fgFLOAT32,volume->type,dat,volume);
}
void flgr1d_measure_volume_fgFLOAT64(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_MEASURE_VOLUME1D_PREDISPATCH(fgFLOAT64,volume->type,dat,volume);
}


////////////////////////////////////////////////////////////////////////////
/*! Measure1d volume
 *
 *  Volume vector type is independent of Data1D type.
 *
 *  Volume type must be (fgUINT32,fgUINT64,fgINT32,fgINT64,fgFLOAT32,fgFLOAT64)
 *
 *  @param dat : pointer to the FLGR_Data1D
 *  @param volume : pointer a variable.
 *  @returns FLGR_RET_OK, ...
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr1d_measure_volume(FLGR_Data1D *dat, FLGR_Vector *volume) {
  FLGR_DECLARE_FUNCTION;

  if((dat == NULL) || (volume==NULL)) {
    POST_ERROR("Null object\n");
    return FLGR_RET_NULL_OBJECT;
  }

  FLGR_DISPATCH_PROCEDURE(dat->type,flgr1d_measure_volume,dat,volume);
}





#define FLGR1D_MACRO_MEASURE_EXPECTED_VALUE(dtype,dtypeV)	\
  dtype *psrc = (dtype*) datsrc->array;				\
  dtypeV *pvec = (dtypeV*) expval->array;			\
  dtype val;							\
  int spp = datsrc->spp;					\
  int len = datsrc->length;					\
  int i,j,k;							\
								\
  for(k=0 ; k<spp ; k++) {					\
    pvec[k]=0;							\
    for(i=0,j=0 ; j<spp*len ; j+=spp,i++) {			\
      val = flgr_get_array_##dtype(psrc,j+k);			\
      pvec[k] += (dtypeV) ((i+1)*val);				\
    }								\
  }								\
								\
  return


void flgr1d_measure_expected_value_u32_fgBIT(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  FLGR1D_MACRO_MEASURE_EXPECTED_VALUE(fgBIT,fgUINT32);
}
void flgr1d_measure_expected_value_u32_fgUINT8(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  FLGR1D_MACRO_MEASURE_EXPECTED_VALUE(fgUINT8,fgUINT32);
}
void flgr1d_measure_expected_value_u32_fgUINT16(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  FLGR1D_MACRO_MEASURE_EXPECTED_VALUE(fgUINT16,fgUINT32);
}
void flgr1d_measure_expected_value_u32_fgUINT32(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  FLGR1D_MACRO_MEASURE_EXPECTED_VALUE(fgUINT32,fgUINT32);
}
void flgr1d_measure_expected_value_u32_fgINT8(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  flgr_no_define_type_function(FLGR_INT8);
}
void flgr1d_measure_expected_value_u32_fgINT16(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  flgr_no_define_type_function(FLGR_INT16);
}
void flgr1d_measure_expected_value_u32_fgINT32(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  flgr_no_define_type_function(FLGR_INT32);
}
void flgr1d_measure_expected_value_u32_fgFLOAT32(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  flgr_no_define_type_function(FLGR_FLOAT32);
}
void flgr1d_measure_expected_value_u32_fgFLOAT64(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  flgr_no_define_type_function(FLGR_FLOAT64);
}

void flgr1d_measure_expected_value_s32_fgBIT(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  flgr_no_define_type_function(FLGR_BIT);
}
void flgr1d_measure_expected_value_s32_fgUINT8(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  flgr_no_define_type_function(FLGR_UINT8);
}
void flgr1d_measure_expected_value_s32_fgUINT16(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  flgr_no_define_type_function(FLGR_UINT16);
}
void flgr1d_measure_expected_value_s32_fgUINT32(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  flgr_no_define_type_function(FLGR_UINT32);
}
void flgr1d_measure_expected_value_s32_fgINT8(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  FLGR1D_MACRO_MEASURE_EXPECTED_VALUE(fgINT8,fgINT32);
}
void flgr1d_measure_expected_value_s32_fgINT16(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  FLGR1D_MACRO_MEASURE_EXPECTED_VALUE(fgINT16,fgINT32);
}
void flgr1d_measure_expected_value_s32_fgINT32(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  FLGR1D_MACRO_MEASURE_EXPECTED_VALUE(fgINT32,fgINT32);
}
void flgr1d_measure_expected_value_s32_fgFLOAT32(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  flgr_no_define_type_function(FLGR_FLOAT32);
}
void flgr1d_measure_expected_value_s32_fgFLOAT64(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  flgr_no_define_type_function(FLGR_FLOAT64);
}

void flgr1d_measure_expected_value_u64_fgBIT(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  FLGR1D_MACRO_MEASURE_EXPECTED_VALUE(fgBIT,fgUINT64);
}
void flgr1d_measure_expected_value_u64_fgUINT8(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  FLGR1D_MACRO_MEASURE_EXPECTED_VALUE(fgUINT8,fgUINT64);
}
void flgr1d_measure_expected_value_u64_fgUINT16(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  FLGR1D_MACRO_MEASURE_EXPECTED_VALUE(fgUINT16,fgUINT64);
}
void flgr1d_measure_expected_value_u64_fgUINT32(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  FLGR1D_MACRO_MEASURE_EXPECTED_VALUE(fgUINT32,fgUINT64);
}
void flgr1d_measure_expected_value_u64_fgINT8(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  flgr_no_define_type_function(FLGR_INT8);
}
void flgr1d_measure_expected_value_u64_fgINT16(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  flgr_no_define_type_function(FLGR_INT16);
}
void flgr1d_measure_expected_value_u64_fgINT32(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  flgr_no_define_type_function(FLGR_INT32);
}
void flgr1d_measure_expected_value_u64_fgFLOAT32(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  flgr_no_define_type_function(FLGR_FLOAT32);
}
void flgr1d_measure_expected_value_u64_fgFLOAT64(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  flgr_no_define_type_function(FLGR_FLOAT64);
}

void flgr1d_measure_expected_value_s64_fgBIT(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  flgr_no_define_type_function(FLGR_BIT);
}
void flgr1d_measure_expected_value_s64_fgUINT8(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  flgr_no_define_type_function(FLGR_UINT8);
}
void flgr1d_measure_expected_value_s64_fgUINT16(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  flgr_no_define_type_function(FLGR_UINT16);
}
void flgr1d_measure_expected_value_s64_fgUINT32(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  flgr_no_define_type_function(FLGR_UINT32);
}
void flgr1d_measure_expected_value_s64_fgINT8(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  FLGR1D_MACRO_MEASURE_EXPECTED_VALUE(fgINT8,fgINT64);
}
void flgr1d_measure_expected_value_s64_fgINT16(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  FLGR1D_MACRO_MEASURE_EXPECTED_VALUE(fgINT16,fgINT64);
}
void flgr1d_measure_expected_value_s64_fgINT32(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  FLGR1D_MACRO_MEASURE_EXPECTED_VALUE(fgINT32,fgINT64);
}
void flgr1d_measure_expected_value_s64_fgFLOAT32(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  flgr_no_define_type_function(FLGR_FLOAT32);
}
void flgr1d_measure_expected_value_s64_fgFLOAT64(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  flgr_no_define_type_function(FLGR_FLOAT64);
}

void flgr1d_measure_expected_value_f32_fgBIT(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  FLGR1D_MACRO_MEASURE_EXPECTED_VALUE(fgBIT,fgFLOAT32);
}
void flgr1d_measure_expected_value_f32_fgUINT8(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  FLGR1D_MACRO_MEASURE_EXPECTED_VALUE(fgUINT8,fgFLOAT32);
}
void flgr1d_measure_expected_value_f32_fgUINT16(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  FLGR1D_MACRO_MEASURE_EXPECTED_VALUE(fgUINT16,fgFLOAT32);
}
void flgr1d_measure_expected_value_f32_fgUINT32(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  FLGR1D_MACRO_MEASURE_EXPECTED_VALUE(fgUINT32,fgFLOAT32);
}
void flgr1d_measure_expected_value_f32_fgINT8(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  FLGR1D_MACRO_MEASURE_EXPECTED_VALUE(fgINT8,fgFLOAT32);
}
void flgr1d_measure_expected_value_f32_fgINT16(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  FLGR1D_MACRO_MEASURE_EXPECTED_VALUE(fgINT16,fgFLOAT32);
}
void flgr1d_measure_expected_value_f32_fgINT32(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  FLGR1D_MACRO_MEASURE_EXPECTED_VALUE(fgINT32,fgFLOAT32);
}
void flgr1d_measure_expected_value_f32_fgFLOAT32(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  FLGR1D_MACRO_MEASURE_EXPECTED_VALUE(fgFLOAT32,fgFLOAT32);
}
void flgr1d_measure_expected_value_f32_fgFLOAT64(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  FLGR1D_MACRO_MEASURE_EXPECTED_VALUE(fgFLOAT64,fgFLOAT32);
}

void flgr1d_measure_expected_value_f64_fgBIT(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  FLGR1D_MACRO_MEASURE_EXPECTED_VALUE(fgBIT,fgFLOAT64);
}
void flgr1d_measure_expected_value_f64_fgUINT8(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  FLGR1D_MACRO_MEASURE_EXPECTED_VALUE(fgUINT8,fgFLOAT64);
}
void flgr1d_measure_expected_value_f64_fgUINT16(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  FLGR1D_MACRO_MEASURE_EXPECTED_VALUE(fgUINT16,fgFLOAT64);
}
void flgr1d_measure_expected_value_f64_fgUINT32(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  FLGR1D_MACRO_MEASURE_EXPECTED_VALUE(fgUINT32,fgFLOAT64);
}
void flgr1d_measure_expected_value_f64_fgINT8(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  FLGR1D_MACRO_MEASURE_EXPECTED_VALUE(fgINT8,fgFLOAT64);
}
void flgr1d_measure_expected_value_f64_fgINT16(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  FLGR1D_MACRO_MEASURE_EXPECTED_VALUE(fgINT16,fgFLOAT64);
}
void flgr1d_measure_expected_value_f64_fgINT32(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  FLGR1D_MACRO_MEASURE_EXPECTED_VALUE(fgINT32,fgFLOAT64);
}
void flgr1d_measure_expected_value_f64_fgFLOAT32(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  FLGR1D_MACRO_MEASURE_EXPECTED_VALUE(fgFLOAT32,fgFLOAT64);
}
void flgr1d_measure_expected_value_f64_fgFLOAT64(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  FLGR1D_MACRO_MEASURE_EXPECTED_VALUE(fgFLOAT64,fgFLOAT64);
}

#define FLGR1D_MEASURE_EXP_VAL_PREDISPATCH(dtype,vector_type,...)	\
  switch(vector_type) {							\
  case FLGR_UINT32:							\
    flgr1d_measure_expected_value_u32_##dtype(__VA_ARGS__);break;	\
  case FLGR_UINT64:							\
    flgr1d_measure_expected_value_u64_##dtype(__VA_ARGS__);break;	\
  case FLGR_INT32:							\
    flgr1d_measure_expected_value_s32_##dtype(__VA_ARGS__);break;	\
  case FLGR_INT64:							\
    flgr1d_measure_expected_value_s64_##dtype(__VA_ARGS__);break;	\
  case FLGR_FLOAT32:							\
    flgr1d_measure_expected_value_f32_##dtype(__VA_ARGS__);break;	\
  case FLGR_FLOAT64:							\
    flgr1d_measure_expected_value_f64_##dtype(__VA_ARGS__);break;	\
  default:								\
    POST_ERROR("Unsupported expected_value vector type : %s\n",		\
	       flgr_get_type_string(vector_type));			\
  }									\
  return



void flgr1d_measure_expected_value_fgBIT(FLGR_Data1D *dat, FLGR_Vector *expected_value) {
  FLGR1D_MEASURE_EXP_VAL_PREDISPATCH(fgBIT,expected_value->type,dat,expected_value);
}
void flgr1d_measure_expected_value_fgUINT8(FLGR_Data1D *dat, FLGR_Vector *expected_value) {
  FLGR1D_MEASURE_EXP_VAL_PREDISPATCH(fgUINT8,expected_value->type,dat,expected_value);
}
void flgr1d_measure_expected_value_fgUINT16(FLGR_Data1D *dat, FLGR_Vector *expected_value) {
  FLGR1D_MEASURE_EXP_VAL_PREDISPATCH(fgUINT16,expected_value->type,dat,expected_value);
}
void flgr1d_measure_expected_value_fgUINT32(FLGR_Data1D *dat, FLGR_Vector *expected_value) {
  FLGR1D_MEASURE_EXP_VAL_PREDISPATCH(fgUINT32,expected_value->type,dat,expected_value);
}
void flgr1d_measure_expected_value_fgINT8(FLGR_Data1D *dat, FLGR_Vector *expected_value) {
  FLGR1D_MEASURE_EXP_VAL_PREDISPATCH(fgINT8,expected_value->type,dat,expected_value);
}
void flgr1d_measure_expected_value_fgINT16(FLGR_Data1D *dat, FLGR_Vector *expected_value) {
  FLGR1D_MEASURE_EXP_VAL_PREDISPATCH(fgINT16,expected_value->type,dat,expected_value);
}
void flgr1d_measure_expected_value_fgINT32(FLGR_Data1D *dat, FLGR_Vector *expected_value) {
  FLGR1D_MEASURE_EXP_VAL_PREDISPATCH(fgINT32,expected_value->type,dat,expected_value);
}
void flgr1d_measure_expected_value_fgFLOAT32(FLGR_Data1D *dat, FLGR_Vector *expected_value) {
  FLGR1D_MEASURE_EXP_VAL_PREDISPATCH(fgFLOAT32,expected_value->type,dat,expected_value);
}
void flgr1d_measure_expected_value_fgFLOAT64(FLGR_Data1D *dat, FLGR_Vector *expected_value) {
  FLGR1D_MEASURE_EXP_VAL_PREDISPATCH(fgFLOAT64,expected_value->type,dat,expected_value);
}


////////////////////////////////////////////////////////////////////////////
/*! Measure the expected value
 *
 *  @param dat : pointer to the FLGR_Data1D
 *  @param expval : pointer a vector.
 *  @returns FLGR_RET_OK, ...
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr1d_measure_expected_value(FLGR_Data1D *datsrc, FLGR_Vector *expval) {
  FLGR_DECLARE_FUNCTION;

  if((datsrc == NULL) || (expval==NULL)) {
    POST_ERROR("Null object\n");
    return FLGR_RET_NULL_OBJECT;
  }

  FLGR_DISPATCH_PROCEDURE(datsrc->type,flgr1d_measure_expected_value,datsrc,expval);
  return FLGR_RET_OK;
}







/******************************************************** 2D *********************************************************/

#define FLGR_MACRO_MEASURE2D_MIN_MAX(dtype)				\
  FLGR_Data1D **pdat = dat->row;					\
  FLGR_Vector *vec1 = flgr_vector_create(dat->spp, dat->type);		\
  FLGR_Vector *vec2 = flgr_vector_create(dat->spp, dat->type);		\
  int i;								\
 									\
  FLGR_DECLARE_FUNCTION;						\
									\
  flgr1d_measure_min_max_##dtype(*pdat++,mini,maxi);			\
									\
  for(i=1 ; i<dat->size_y ; i++,pdat++) {				\
    flgr1d_measure_min_max_##dtype(*pdat,vec1,vec2);			\
    flgr_vector_inf_##dtype(mini,vec1,mini);				\
    flgr_vector_sup_##dtype(maxi,vec2,maxi);				\
  }									\
									\
  flgr_vector_destroy(vec1);						\
  flgr_vector_destroy(vec2)


void flgr2d_measure_min_max_fgBIT(FLGR_Data2D *dat, FLGR_Vector *mini, FLGR_Vector *maxi) {
  FLGR_MACRO_MEASURE2D_MIN_MAX(fgBIT);
}

void flgr2d_measure_min_max_fgUINT8(FLGR_Data2D *dat, FLGR_Vector *mini, FLGR_Vector *maxi) {
  FLGR_MACRO_MEASURE2D_MIN_MAX(fgUINT8);
}

void flgr2d_measure_min_max_fgUINT16(FLGR_Data2D *dat, FLGR_Vector *mini, FLGR_Vector *maxi) {
  FLGR_MACRO_MEASURE2D_MIN_MAX(fgUINT16);
}

void flgr2d_measure_min_max_fgUINT32(FLGR_Data2D *dat, FLGR_Vector *mini, FLGR_Vector *maxi) {
  FLGR_MACRO_MEASURE2D_MIN_MAX(fgUINT32);
}

void flgr2d_measure_min_max_fgINT8(FLGR_Data2D *dat, FLGR_Vector *mini, FLGR_Vector *maxi) {
  FLGR_MACRO_MEASURE2D_MIN_MAX(fgINT8);
}

void flgr2d_measure_min_max_fgINT16(FLGR_Data2D *dat, FLGR_Vector *mini, FLGR_Vector *maxi) {
  FLGR_MACRO_MEASURE2D_MIN_MAX(fgINT16);
}

void flgr2d_measure_min_max_fgINT32(FLGR_Data2D *dat, FLGR_Vector *mini, FLGR_Vector *maxi) {
  FLGR_MACRO_MEASURE2D_MIN_MAX(fgINT32);
}

void flgr2d_measure_min_max_fgFLOAT32(FLGR_Data2D *dat, FLGR_Vector *mini, FLGR_Vector *maxi) {
  FLGR_MACRO_MEASURE2D_MIN_MAX(fgFLOAT32);
}

void flgr2d_measure_min_max_fgFLOAT64(FLGR_Data2D *dat, FLGR_Vector *mini, FLGR_Vector *maxi) {
  FLGR_MACRO_MEASURE2D_MIN_MAX(fgFLOAT64);
}

////////////////////////////////////////////////////////////////////////////
/*! Measure2d minimum and maximum
 *  @param dat : pointer to the FLGR_Data2D
 *  @param minimum : pointer a variable. Variable type must correspond with to dat->type
 *  @param maximum : pointer a variable. Variable type must correspond with to dat->type
 *  @returns FLGR_RET_OK, ...
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr2d_measure_min_max(FLGR_Data2D *dat, FLGR_Vector *minimum, FLGR_Vector *maximum) {
  FLGR_DECLARE_FUNCTION;

  if((dat==NULL) || (minimum==NULL) || (maximum==NULL)){
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  if(dat->spp != minimum->spp) {
    POST_ERROR("Sample per pixel are different\n");
    return FLGR_RET_UNDEFINED_ERROR;
  }

  if(dat->spp != maximum->spp) {
    POST_ERROR("Sample per pixel are different\n");
    return FLGR_RET_UNDEFINED_ERROR;
  }

  FLGR_DISPATCH_PROCEDURE(dat->type,flgr2d_measure_min_max,dat,minimum,maximum);

}














#define FLGR_MACRO_MEASURE2D_VOLUME_U32(dtype)				\
  FLGR_Data1D **pdat = dat->row;					\
  FLGR_Vector *vec = flgr_vector_create(volume->spp, FLGR_UINT32);	\
  int i;								\
									\
  FLGR_DECLARE_FUNCTION;						\
									\
  flgr_vector_clear(volume);						\
									\
  for(i=0 ; i<dat->size_y ; i++,pdat++) {				\
    flgr1d_measure_volume_u32_##dtype(*pdat,vec);			\
    flgr_vector_add_fgUINT32(volume,volume,vec);			\
  }									\
  flgr_vector_destroy(vec)


#define FLGR_MACRO_MEASURE2D_VOLUME_S32(dtype)				\
  FLGR_Data1D **pdat = dat->row;					\
  FLGR_Vector *vec = flgr_vector_create(volume->spp, FLGR_INT32);	\
  int i;								\
									\
  FLGR_DECLARE_FUNCTION;						\
									\
  flgr_vector_clear(volume);						\
									\
  for(i=0 ; i<dat->size_y ; i++,pdat++) {				\
    flgr1d_measure_volume_s32_##dtype(*pdat,vec);			\
    flgr_vector_add_fgINT32(volume,volume,vec);				\
  }									\
  flgr_vector_destroy(vec)


#define FLGR_MACRO_MEASURE2D_VOLUME_U64(dtype)				\
  FLGR_Data1D **pdat = dat->row;					\
  FLGR_Vector *vec = flgr_vector_create(volume->spp, FLGR_UINT64);	\
  int i;								\
									\
  FLGR_DECLARE_FUNCTION;						\
									\
  flgr_vector_clear(volume);						\
									\
  for(i=0 ; i<dat->size_y ; i++,pdat++) {				\
    flgr1d_measure_volume_u64_##dtype(*pdat,vec);			\
    flgr_vector_add_fgUINT64(volume,volume,vec);			\
  }									\
  flgr_vector_destroy(vec)

#define FLGR_MACRO_MEASURE2D_VOLUME_S64(dtype)				\
  FLGR_Data1D **pdat = dat->row;					\
  FLGR_Vector *vec = flgr_vector_create(volume->spp, FLGR_INT64);	\
  int i;								\
									\
  FLGR_DECLARE_FUNCTION;						\
									\
  flgr_vector_clear(volume);						\
									\
  for(i=0 ; i<dat->size_y ; i++,pdat++) {				\
    flgr1d_measure_volume_s64_##dtype(*pdat,vec);			\
    flgr_vector_add_fgINT64(volume,volume,vec);				\
  }									\
  flgr_vector_destroy(vec)


#define FLGR_MACRO_MEASURE2D_VOLUME_F32(dtype)				\
  FLGR_Data1D **pdat = dat->row;					\
  FLGR_Vector *vec = flgr_vector_create(volume->spp, FLGR_FLOAT32);	\
  int i;								\
									\
  FLGR_DECLARE_FUNCTION;						\
									\
  flgr_vector_clear(volume);						\
									\
  for(i=0 ; i<dat->size_y ; i++,pdat++) {				\
    flgr1d_measure_volume_f32_##dtype(*pdat,vec);			\
    flgr_vector_add_fgFLOAT32(volume,volume,vec);			\
  }									\
  flgr_vector_destroy(vec)

#define FLGR_MACRO_MEASURE2D_VOLUME_F64(dtype)				\
  FLGR_Data1D **pdat = dat->row;					\
  FLGR_Vector *vec = flgr_vector_create(volume->spp, FLGR_FLOAT64);	\
  int i;								\
									\
  FLGR_DECLARE_FUNCTION;						\
									\
  flgr_vector_clear(volume);						\
									\
  for(i=0 ; i<dat->size_y ; i++,pdat++) {				\
    flgr1d_measure_volume_f64_##dtype(*pdat,vec);			\
    flgr_vector_add_fgFLOAT64(volume,volume,vec);			\
  }									\
  flgr_vector_destroy(vec)


#define FLGR_MACRO_MEASURE2D_VOLUME(dtype,dtype_volume)			\
  FLGR_Vector *tmp = flgr_vector_create(dat->spp, dat->type);		\
  FLGR_Vector *tmp2 = flgr_vector_create(volume->spp, volume->type);	\
  int i,j;								\
									\
  FLGR_DECLARE_FUNCTION;						\
									\
  flgr_vector_clear(tmp);						\
  flgr_vector_clear(tmp2);						\
  flgr_vector_clear(volume);						\
  									\
  for(i=0 ; i<dat->size_y ; i++) {					\
    for(j=0 ; j<dat->size_x ; j++) {					\
      flgr2d_get_data_vector_##dtype(dat,i,j,tmp);			\
      flgr_vector_copy_##dtype_volume##_##dtype(tmp2,tmp);		\
      flgr_vector_add_##dtype(volume,tmp2,volume);			\
    }									\
  }									\
									\
  flgr_vector_destroy(tmp);						\
  flgr_vector_destroy(tmp2);						\
									\
  return



void flgr2d_measure_volume_u32_fgBIT(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_U32(fgBIT);
}
void flgr2d_measure_volume_u32_fgUINT8(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_U32(fgUINT8);
}
void flgr2d_measure_volume_u32_fgUINT16(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_U32(fgUINT16);
}
void flgr2d_measure_volume_u32_fgUINT32(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_U32(fgUINT32);
}
void flgr2d_measure_volume_u32_fgINT8(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_U32(fgINT8);
}
void flgr2d_measure_volume_u32_fgINT16(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_U32(fgINT16);
}
void flgr2d_measure_volume_u32_fgINT32(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_U32(fgINT32);
}
void flgr2d_measure_volume_u32_fgFLOAT32(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_U32(fgFLOAT32);
}
void flgr2d_measure_volume_u32_fgFLOAT64(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_U32(fgFLOAT64);
}




void flgr2d_measure_volume_s32_fgBIT(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_S32(fgBIT);
}
void flgr2d_measure_volume_s32_fgUINT8(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_S32(fgUINT8);
}
void flgr2d_measure_volume_s32_fgUINT16(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_S32(fgUINT16);
}
void flgr2d_measure_volume_s32_fgUINT32(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_S32(fgUINT32);
}
void flgr2d_measure_volume_s32_fgINT8(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_S32(fgINT8);
}
void flgr2d_measure_volume_s32_fgINT16(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_S32(fgINT16);
}
void flgr2d_measure_volume_s32_fgINT32(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_S32(fgINT32);
}
void flgr2d_measure_volume_s32_fgFLOAT32(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_S32(fgFLOAT32);
}
void flgr2d_measure_volume_s32_fgFLOAT64(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_S32(fgFLOAT64);
}





void flgr2d_measure_volume_u64_fgBIT(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_U64(fgBIT);
}
void flgr2d_measure_volume_u64_fgUINT8(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_U64(fgUINT8);
}
void flgr2d_measure_volume_u64_fgUINT16(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_U64(fgUINT16);
}
void flgr2d_measure_volume_u64_fgUINT32(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_U64(fgUINT32);
}
void flgr2d_measure_volume_u64_fgINT8(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_U64(fgINT8);
}
void flgr2d_measure_volume_u64_fgINT16(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_U64(fgINT16);
}
void flgr2d_measure_volume_u64_fgINT32(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_U64(fgINT32);
}
void flgr2d_measure_volume_u64_fgFLOAT32(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_U64(fgFLOAT32);
}
void flgr2d_measure_volume_u64_fgFLOAT64(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_U64(fgFLOAT64);
}




void flgr2d_measure_volume_s64_fgBIT(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_S64(fgBIT);
}
void flgr2d_measure_volume_s64_fgUINT8(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_S64(fgUINT8);
}
void flgr2d_measure_volume_s64_fgUINT16(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_S64(fgUINT16);
}
void flgr2d_measure_volume_s64_fgUINT32(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_S64(fgUINT32);
}
void flgr2d_measure_volume_s64_fgINT8(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_S64(fgINT8);
}
void flgr2d_measure_volume_s64_fgINT16(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_S64(fgINT16);
}
void flgr2d_measure_volume_s64_fgINT32(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_S64(fgINT32);
}
void flgr2d_measure_volume_s64_fgFLOAT32(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_S64(fgFLOAT32);
}
void flgr2d_measure_volume_s64_fgFLOAT64(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_S64(fgFLOAT64);
}








void flgr2d_measure_volume_f32_fgBIT(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_F32(fgBIT);
}
void flgr2d_measure_volume_f32_fgUINT8(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_F32(fgUINT8);
}
void flgr2d_measure_volume_f32_fgUINT16(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_F32(fgUINT16);
}
void flgr2d_measure_volume_f32_fgUINT32(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_F32(fgUINT32);
}
void flgr2d_measure_volume_f32_fgINT8(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_F32(fgINT8);
}
void flgr2d_measure_volume_f32_fgINT16(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_F32(fgINT16);
}
void flgr2d_measure_volume_f32_fgINT32(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_F32(fgINT32);
}
void flgr2d_measure_volume_f32_fgFLOAT32(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_F32(fgFLOAT32);
}
void flgr2d_measure_volume_f32_fgFLOAT64(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_F32(fgFLOAT64);
}




void flgr2d_measure_volume_f64_fgBIT(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_F64(fgBIT);
}
void flgr2d_measure_volume_f64_fgUINT8(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_F64(fgUINT8);
}
void flgr2d_measure_volume_f64_fgUINT16(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_F64(fgUINT16);
}
void flgr2d_measure_volume_f64_fgUINT32(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_F64(fgUINT32);
}
void flgr2d_measure_volume_f64_fgINT8(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_F64(fgINT8);
}
void flgr2d_measure_volume_f64_fgINT16(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_F64(fgINT16);
}
void flgr2d_measure_volume_f64_fgINT32(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_F64(fgINT32);
}
void flgr2d_measure_volume_f64_fgFLOAT32(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_F64(fgFLOAT32);
}
void flgr2d_measure_volume_f64_fgFLOAT64(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MACRO_MEASURE2D_VOLUME_F64(fgFLOAT64);
}



#define FLGR_MEASURE_VOLUME2D_PREDISPATCH(dtype,vector_type,...)	\
  switch(vector_type) {							\
  case FLGR_UINT32:							\
    flgr2d_measure_volume_u32_##dtype(__VA_ARGS__);break;		\
  case FLGR_UINT64:							\
    flgr2d_measure_volume_u64_##dtype(__VA_ARGS__);break;		\
  case FLGR_INT32:							\
    flgr2d_measure_volume_s32_##dtype(__VA_ARGS__);break;		\
  case FLGR_INT64:							\
    flgr2d_measure_volume_s64_##dtype(__VA_ARGS__);break;		\
  case FLGR_FLOAT32:							\
    flgr2d_measure_volume_f32_##dtype(__VA_ARGS__);break;		\
  case FLGR_FLOAT64:							\
    flgr2d_measure_volume_f64_##dtype(__VA_ARGS__);break;		\
  default:								\
    POST_ERROR("Unsupported volume vector type : %s\n",			\
	       flgr_get_type_string(vector_type));			\
  }									\
  return



void flgr2d_measure_volume_fgBIT(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MEASURE_VOLUME2D_PREDISPATCH(fgBIT,volume->type,dat,volume);
}
void flgr2d_measure_volume_fgUINT8(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MEASURE_VOLUME2D_PREDISPATCH(fgUINT8,volume->type,dat,volume);
}
void flgr2d_measure_volume_fgUINT16(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MEASURE_VOLUME2D_PREDISPATCH(fgUINT16,volume->type,dat,volume);
}
void flgr2d_measure_volume_fgUINT32(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MEASURE_VOLUME2D_PREDISPATCH(fgUINT32,volume->type,dat,volume);
}
void flgr2d_measure_volume_fgINT8(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MEASURE_VOLUME2D_PREDISPATCH(fgINT8,volume->type,dat,volume);
}
void flgr2d_measure_volume_fgINT16(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MEASURE_VOLUME2D_PREDISPATCH(fgINT16,volume->type,dat,volume);
}
void flgr2d_measure_volume_fgINT32(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MEASURE_VOLUME2D_PREDISPATCH(fgINT32,volume->type,dat,volume);
}
void flgr2d_measure_volume_fgFLOAT32(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MEASURE_VOLUME2D_PREDISPATCH(fgFLOAT32,volume->type,dat,volume);
}
void flgr2d_measure_volume_fgFLOAT64(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_MEASURE_VOLUME2D_PREDISPATCH(fgFLOAT64,volume->type,dat,volume);
}


////////////////////////////////////////////////////////////////////////////
/*! Measure2d volume
 *
 *  Volume vector type is independent of Data2D type.
 *
 *  Volume type must be (fgUINT32,fgUINT64,fgINT32,fgINT64,fgFLOAT32,fgFLOAT64)
 *
 *  @param dat : pointer to the FLGR_Data2D
 *  @param volume : pointer a variable.
 *  @returns FLGR_RET_OK, ...
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr2d_measure_volume(FLGR_Data2D *dat, FLGR_Vector *volume) {
  FLGR_DECLARE_FUNCTION;
  if((dat == NULL) || (volume==NULL)) {
    POST_ERROR("Null object\n");
    return FLGR_RET_NULL_OBJECT;
  }

  FLGR_DISPATCH_PROCEDURE(dat->type,flgr2d_measure_volume,dat,volume);
}







//! @}
